#include <vector>
#include "gtest/gtest.h"
#include "session.h"

using namespace simple;

TEST(session_test, setAttribute) {
    Session session(STDOUT_FILENO);

    session.setAttribute("key1", 1);
    session.setAttribute("key3", 3.14);
    session.setAttribute("key4", true);
    session.setAttribute("key5", nullptr);
    session.setAttribute("key6", std::string("value6"));
    session.setAttribute("key7", std::vector<int>{1, 2, 3});
    session.setAttribute("key8", std::map<std::string, int>{{"key1", 1}, {"key2", 2}});
    session.setAttribute("key9", std::make_shared<int>(10));
    session.setAttribute("key10", std::make_shared<std::string>("value10"));
    session.setAttribute("key11", std::make_shared<std::vector<int>>(std::vector<int>{1, 2, 3}));
}

TEST(session_test, isAttributeExist) {
    Session session(STDOUT_FILENO);
    session.setAttribute("key1", 1);
    EXPECT_TRUE(session.isAttributeExist("key1"));

    session.setAttribute("key3", 3.14);
    EXPECT_TRUE(session.isAttributeExist("key3"));

    EXPECT_FALSE(session.isAttributeExist("key4"));
}

TEST(session_test, getAttribute) {
    Session session(STDOUT_FILENO);
    session.setAttribute("key1", 1);
    EXPECT_EQ(session.getAttribute<int>("key1"), 1);

    session.setAttribute("key3", 3.14);
    EXPECT_EQ(session.getAttribute<double>("key3"), 3.14);

    session.setAttribute("key4", true);
    EXPECT_EQ(session.getAttribute<bool>("key4"), true);

    // session.setAttribute("key5", nullptr);
    // EXPECT_EQ(session.getAttribute<void*>("key5"), nullptr);

    session.setAttribute("key6", std::string("value6"));
    EXPECT_EQ(session.getAttribute<std::string>("key6"), "value6");

    auto vec = std::vector<int>{1, 2, 3};
    session.setAttribute("key7", vec);
    EXPECT_EQ(session.getAttribute<std::vector<int>>("key7"), vec);

    auto map = std::map<std::string, int>{{"key1", 1}, {"key2", 2}};
    session.setAttribute("key8", map);
    auto map2 = session.getAttribute<std::map<std::string, int>>("key8");
    EXPECT_EQ(map, map2);

    auto ptr1 = std::make_shared<int>(10);
    session.setAttribute("key9", ptr1);
    EXPECT_EQ(session.getAttribute<std::shared_ptr<int>>("key9"), ptr1);

    auto ptr2 = std::make_shared<std::string>("value10");
    session.setAttribute("key10", ptr2);

    auto ptr3 = std::make_shared<std::vector<int>>(std::vector<int>{1, 2, 3});
    session.setAttribute("key11", ptr3);
}

TEST(session_test, getAttribute_default) {
    Session session(STDOUT_FILENO);

    EXPECT_EQ(session.getAttribute<int>("key1", 1), 1);
    EXPECT_EQ(session.getAttribute<void*>("key2", nullptr), nullptr);
}

TEST(session_test, popAttribute) {
    Session session(STDOUT_FILENO);

    session.setAttribute("key1", 1);
    EXPECT_TRUE(session.isAttributeExist("key1"));
    EXPECT_EQ(session.popAttribute<int>("key1"), 1);
    EXPECT_FALSE(session.isAttributeExist("key1"));
}

TEST(session_test, removeAttribute) {
    Session session(STDOUT_FILENO);

    session.setAttribute("key1", 1);
    EXPECT_TRUE(session.isAttributeExist("key1"));
    EXPECT_TRUE(session.removeAttribute("key1"));
    EXPECT_FALSE(session.isAttributeExist("key1"));
}

TEST(session_test, resetAttribute) {
    Session session(STDOUT_FILENO);

    session.setAttribute("key1", 1);
    session.setAttribute("key2", 2);
    session.setAttribute("key3", 3);

    session.resetAttribute();

    EXPECT_FALSE(session.isAttributeExist("key1"));
    EXPECT_FALSE(session.isAttributeExist("key2"));
}